#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (c) 2021 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import os
import sys
import argparse
import shutil

sys.path.append(
    os.path.dirname(os.path.dirname(os.path.dirname(
        os.path.abspath(__file__)))))
from scripts.util.file_utils import read_json_file, write_json_file, write_file  # noqa: E402, E501

def _get_product_config(config_dir, product_name):
    config_file = os.path.join(config_dir, '{}.json'.format(product_name))
    if not os.path.exists(config_file):
        raise Exception(
            "product configuration '{}' doesn't exist.".format(config_file))
    return config_file


def _get_base_parts(base_config_dir, os_level):
    system_base_config_file = os.path.join(base_config_dir,
                                           '{}_system.json'.format(os_level))
    if not os.path.exists(system_base_config_file):
        raise Exception("product configuration '{}' doesn't exist.".format(
            system_base_config_file))
    data = read_json_file(system_base_config_file)
    if data is None:
        raise Exception(
            "read file '{}' failed.".format(system_base_config_file))
    return data


def _get_inherit_parts(inherit_config, current_path):
    _parts = {}
    for _config in inherit_config:
        _file = os.path.join(current_path, _config)
        _info = read_json_file(_file)
        if _info is None:
            raise Exception("read file '{}' failed.".format(_file))
        if _info.get('parts'):
            _parts.update(_info.get('parts'))
    return _parts


def _get_device_info(device_name, device_config_path):
    device_config_file = os.path.join(device_config_path,
                                      '{}.json'.format(device_name))
    device_info = read_json_file(device_config_file)
    if device_info and device_info.get('device_name') != device_name:
        raise Exception("device name configuration incorrect in '{}'".format(
            device_config_file))
    return device_info

def _parse_config_v2(config_info, products_config_path, base_config_dir,
                     device_config_path):
    os_level = config_info.get("type")
    base_parts = _get_base_parts(base_config_dir, os_level)
    all_parts = base_parts

    inherit_config = config_info.get('inherit')
    if inherit_config:
        inherit_parts = _get_inherit_parts(inherit_config,
                                           products_config_path)
        if inherit_parts:
            all_parts.update(inherit_parts)

    current_product_parts = config_info.get("parts")
    if current_product_parts:
        all_parts.update(current_product_parts)

    product_name = config_info.get('product_name')
    product_company = config_info.get('product_company')
    product_device_name = config_info.get('product_device')
    build_configs = {}
    if product_device_name:
        device_info = _get_device_info(product_device_name, device_config_path)
        if device_info:
            build_configs.update(device_info)
    build_configs['os_level'] = os_level
    build_configs['product_name'] = product_name
    build_configs['product_company'] = product_company
    build_configs['device_name'] = product_device_name
    return all_parts, build_configs


def _parse_config_v1(config_info):
    build_configs = {"os_level": 'large'}
    return {}, build_configs


def _parse_config(product_name, products_config_path, base_parts_config_path,
                  device_config_path):
    curr_config_file = _get_product_config(products_config_path, product_name)
    config_info = read_json_file(curr_config_file)
    config_version = None
    if config_info:
        config_version = config_info.get('version')
    if not config_version:
        config_version = "1.0"
    if config_version == "2.0":
        if config_info and product_name != config_info.get('product_name'):
            raise Exception(
                "product name configuration incorrect in '{}'".format(
                    curr_config_file))
        return _parse_config_v2(config_info, products_config_path,
                                base_parts_config_path, device_config_path)
    else:
        return _parse_config_v1(config_info)

proprietary_parts = []

def _run(args):
    products_config_path = os.path.join(args.source_root_dir,
                                        args.products_config_dir)
    print("args.source_root_dir:" + args.source_root_dir)
    print("args.products_config_dir:" + args.products_config_dir)
    print("products_config_path:" + products_config_path)
    product_config_root_path = os.path.dirname(products_config_path)
    root_dir = args.source_root_dir
    if args.base_parts_config_dir:
        base_parts_config_path = os.path.join(args.source_root_dir,
                                              args.base_parts_config_dir)
    else:
        base_parts_config_path = os.path.join(product_config_root_path, 'base')
    if args.device_config_dir:
        device_config_path = os.path.join(args.source_root_dir,
                                          args.device_config_dir)
    else:
        device_config_path = os.path.join(product_config_root_path, 'device')

    all_parts, build_configs = _parse_config(args.product_name,
                                             products_config_path,
                                             base_parts_config_path,
                                             device_config_path)

    # 获取proprietary化的组件
    print("===Get proprietary parts===")
    for part in all_parts:
        if 'proprietary' in all_parts[part] and all_parts[part]['proprietary']:
            print(part)
            proprietary_parts.append(part.split(':')[1])
    print("===Get proprietary parts done===")
    
    # 根据配置，获得out目录具体位置
    out_dir = args.source_root_dir + "/out/ohos-arm-release"

    # 从out中读取path_to_parts.json，找到模块代码路径(TODO)
    path_to_parts = read_json_file(out_dir + "/build_configs/parts_info/path_to_parts.json")

    # 读取system_module_info.json，获得模块二进制路径、原始模块路径、LICENSE信息、类型信息(TODO)
    system_module_info = read_json_file(out_dir + "/packages/phone/system_module_info.json")

    for proprietary_part in proprietary_parts:
        print("proprietary_part:" + proprietary_part)
        for code_path in path_to_parts:
            if proprietary_part in path_to_parts[code_path]:
                print("Get code path " + code_path + " for " + proprietary_part) 
                break

        modules = []
        module_list = []
        for module in system_module_info:
            if 'label' in module:
                if module['label'].find('//' + code_path) != 0:
                    continue
            else:
                if module['source'].find('//' + code_path) != 0:
                    continue
            modules.append(module)
            module_list.append(module['label'].split('(')[0].replace(':', "/"))
        
        # 生成目录
        code_path = "/vendor/huawei/proprietary/Hi3516DV300/ohos_clang_arm/" + code_path
        print(root_dir + code_path)
        shutil.rmtree(root_dir + code_path)
        os.makedirs(root_dir + code_path, exist_ok=True)

        # 并根据模块列表填充ohos.build (TODO:一个ohos.build多个模块)
        f = open(root_dir + code_path + '/ohos.build', "w+")
        f.write("{\n}\n")
        f.close()
        ohos_build = read_json_file(root_dir + code_path + '/ohos.build')
        ohos_build['subsystem'] = "developtools"
        ohos_build['parts'] = {}
        ohos_build['parts'][proprietary_part] = {} 
        ohos_build['parts'][proprietary_part]['module_list'] = module_list
        write_json_file(root_dir + code_path + '/ohos.build', ohos_build)
        print(ohos_build)
        
        print(modules)

        # 对每一个模块
        for module in modules:
            module_path = module['label'][2:].split('(')[0].replace(':', '/')
            module_path = '/vendor/huawei/proprietary/Hi3516DV300/ohos_clang_arm/' + module_path
            print("module_path:" + module_path)
            # 根据原始模块路径创建目录
            os.makedirs(root_dir + module_path, exist_ok=True)

            # 拷贝二进制到对应目录
            shutil.copy(os.path.join(out_dir, module['source']), root_dir + module_path)

            # 拷贝License到目录
            shutil.copy(os.path.join(out_dir, module['notice']), root_dir + module_path + '/LICENSE')

            # 建立BUILD.gn
            f = open(root_dir + module_path + '/BUILD.gn', "w+")
            f.write('import("//build/ohos.gni")\n')
            
            if module['type'] == "bin":
                f.write('ohos_prebuilt_executable("' + module['label_name'] + '") {\n')
                f.write('  source = "' + module['label_name'] + '"\n')
                f.write('  install_enable = true\n')
                f.write('  part_name = "' + proprietary_part + '"\n')
                f.write('}\n')


def main(argv):
    parser = argparse.ArgumentParser()
    parser.add_argument('--product-name', required=True)
    parser.add_argument('--source-root-dir', required=True)
    parser.add_argument('--products-config-dir', required=True)
    parser.add_argument('--base-parts-config-dir')
    parser.add_argument('--device-config-dir')
    parser.add_argument('--preloader-output-root-dir', required=True)
    args = parser.parse_args(argv)
    _run(args)
    return 0

if __name__ == '__main__':
    sys.exit(main(sys.argv[1:]))
